package de.preamp.clients.java.data;

import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.SortedSet;

import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

/**
 * This abstract class represents a logical item in the database like artists,
 * albums or tracks to abstract from the preamp server. The specific items
 * should be implemented in the subclasses. The abstract class implements the
 * {@link java.awt.datatransfer.Transferable} interface for Drag and Drop
 * possibility of the DB-items because their implementation of the interface is
 * identical.
 * 
 * @author André Stannek
 * @author Oliver Bestmann
 * @version 2010-07-30
 * @see Artist
 * @see Album
 * @see Track
 */
public abstract class AbstractDBItem implements Transferable
{
    /**
     * ChangeListeners.
     */
    private final transient Set<ChangeListener> listeners;

    /**
     * Constructor.
     */
    public AbstractDBItem()
    {
        this.listeners = new HashSet<>();
    }

    @Override
    public final Object getTransferData(final DataFlavor flavor)
            throws UnsupportedFlavorException, IOException
    {
        if (isDataFlavorSupported(flavor))
        {
            return this;
        }
	throw new UnsupportedFlavorException(flavor);
    }

    @Override
    public abstract DataFlavor[] getTransferDataFlavors();

    @Override
    public final boolean isDataFlavorSupported(final DataFlavor flavor)
    {
        boolean result = false;
        for (final DataFlavor flav : getTransferDataFlavors())
        {
            if (flav.equals(flavor))
            {
                result = true;
            }
        }
        return result;
    }

    /**
     * Adds a ChangeListener to this Item.
     * 
     * @param listener
     *            the ChangeListener to add.
     */
    public final void addChangeListener(final ChangeListener listener)
    {
        this.listeners.add(listener);
    }

    /**
     * Removes a ChangeListener from this Item.
     * 
     * @param listener
     *            the ChangeListener to remove.
     */
    public final void removeChangeListener(final ChangeListener listener)
    {
        this.listeners.remove(listener);
    }

    /**
     * Fires all ChangeListeners.
     */
    protected final void fireChangeListeners()
    {
        for (final ChangeListener listener : this.listeners)
        {
            listener.stateChanged(new ChangeEvent(this));
        }
    }

    /**
     * Returns a Set of all Tracks belonging to this DBItem. If the DBItem is
     * already a Track, the Set will contain this Track.
     * 
     * @return a Set of all Tracks belonging to this DBItem
     */
    public abstract SortedSet<Track> getTracks();

}
